#!/usr/bin/env python
#encoding=utf-8

"""protoc后端输出插件,产生Lua table风格的可读常量"""
"""
Thu Aug 29 03:01:01 CST 2013
"""

import os
from collections import defaultdict
from StringIO import StringIO
from google.protobuf.descriptor import FieldDescriptor
from google.protobuf.compiler.plugin_pb2 import CodeGeneratorRequest, CodeGeneratorResponse
from sys import stdin, stdout, stderr

serialized = stdin.read()
request = CodeGeneratorRequest()
request.ParseFromString(serialized)

# small check
"""
"""


response = CodeGeneratorResponse()

flt_enums = [ "ServiceType", "FieldDescriptorProto_Type"
            , "FieldDescriptorProto_Label", "FileOptions_OptimizeMode"
            , "FieldOptions_CType" ]

def write_enum(fp, package, name, descriptor):
    if name not in flt_enums:
        print >>fp, '%s = {' % name
        appendspaces(descriptor.value)
        for value in descriptor.value:
            print >>fp, '    %s = %d,'%(value.name, value.number)
        print >>fp, '}'

def write_enum2(fp2, package, name, descriptor):
    if name in ["CommandType"] + flt_enums and name[0] == 'S':
        print >> fp2, '%s = {' % name
        fnl = appendspaces2(descriptor.value)
        i = -1
        for value in descriptor.value:
            i = i + 1
            print >> fp2, '    %s = "%s",'%(fnl[i], value.name)
        print >> fp2, '}'

def appendspaces2(values):
    maxnamelen = 0
    # 遍历一遍list,取得最大长度
    rl = []
    for value in values:
        if maxnamelen < len(value.name):
            maxnamelen = len(value.name)
    for value in values:
        v = value.name + " " * (maxnamelen - len(value.name))
        rl.append(v)
    return rl


def appendspaces(values):
    """sherlock实现的补充空格对齐输出的Lua代码功能"""
    maxnamelen = 0
    # 遍历一遍list,取得最大长度
    for value in values:
        if maxnamelen < len(value.name):
            maxnamelen = len(value.name)
    # 遍历,给name后面加上能够对齐的空格数量
    for value in values:
        value.name += " " * (maxnamelen - len(value.name))

def pkg_file(packages):
    fp = StringIO()
    fp2 = StringIO()
    print >> fp,  '-- this code is generated by custom protoc plugin\n'
    print >> fp2, '-- this code is generated by custom protoc plugin, too\n'
    for package, file_descriptors in packages.items():
        for file_descriptor in file_descriptors:
            # top level enum
            for descriptor in file_descriptor.enum_type:
                write_enum2(fp2, package, descriptor.name, descriptor)
                write_enum(fp, package, descriptor.name, descriptor)

            # sub enum type
            for descriptor in file_descriptor.message_type:
                for enum_descriptor in descriptor.enum_type:
                    write_enum2(fp2, package, '%s_%s'%(descriptor.name, enum_descriptor.name), enum_descriptor)
                    write_enum(fp, package, '%s_%s'%(descriptor.name, enum_descriptor.name), enum_descriptor)

    return fp.getvalue(), fp2.getvalue()

packages = defaultdict(list)

for i in range(0, len(request.proto_file)):
    file_descriptor = request.proto_file[i]
    packages[file_descriptor.package].append(file_descriptor)

c1, c2 = pkg_file(packages)
f = response.file.add()
f.name = 'const.lua'
f.content = c1

stdout.write(response.SerializeToString())
